From b186bce7ff4febcb3fd7cd77a0c40ab7dcb4886b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 10 Jan 2017 14:59:20 +0100 Subject: [PATCH] vulkan: Add shader for border rendering --- gsk/Makefile.am | 12 +- gsk/gskrendernodeimpl.c | 12 +- gsk/gskrendernodeprivate.h | 4 +- gsk/gskvulkanborderpipeline.c | 163 ++++++++++++++++++ gsk/gskvulkanborderpipelineprivate.h | 34 ++++ gsk/gskvulkanrender.c | 6 +- gsk/gskvulkanrenderpass.c | 58 ++++++- gsk/gskvulkanrenderprivate.h | 3 + .../vulkan/border-clip-rounded.frag.glsl | 34 ++++ .../vulkan/border-clip-rounded.frag.spv | Bin 0 -> 9832 bytes .../vulkan/border-clip-rounded.vert.glsl | 123 +++++++++++++ .../vulkan/border-clip-rounded.vert.spv | Bin 0 -> 9312 bytes gsk/resources/vulkan/border-clip.frag.glsl | 23 +++ gsk/resources/vulkan/border-clip.frag.spv | Bin 0 -> 9008 bytes gsk/resources/vulkan/border-clip.vert.glsl | 117 +++++++++++++ gsk/resources/vulkan/border-clip.vert.spv | Bin 0 -> 8952 bytes gsk/resources/vulkan/border.frag.glsl | 23 +++ gsk/resources/vulkan/border.frag.spv | Bin 0 -> 9008 bytes gsk/resources/vulkan/border.vert.glsl | 106 ++++++++++++ gsk/resources/vulkan/border.vert.spv | Bin 0 -> 7216 bytes gsk/resources/vulkan/rounded-rect.glsl | 69 ++++++++ 21 files changed, 775 insertions(+), 12 deletions(-) create mode 100644 gsk/gskvulkanborderpipeline.c create mode 100644 gsk/gskvulkanborderpipelineprivate.h create mode 100644 gsk/resources/vulkan/border-clip-rounded.frag.glsl create mode 100644 gsk/resources/vulkan/border-clip-rounded.frag.spv create mode 100644 gsk/resources/vulkan/border-clip-rounded.vert.glsl create mode 100644 gsk/resources/vulkan/border-clip-rounded.vert.spv create mode 100644 gsk/resources/vulkan/border-clip.frag.glsl create mode 100644 gsk/resources/vulkan/border-clip.frag.spv create mode 100644 gsk/resources/vulkan/border-clip.vert.glsl create mode 100644 gsk/resources/vulkan/border-clip.vert.spv create mode 100644 gsk/resources/vulkan/border.frag.glsl create mode 100644 gsk/resources/vulkan/border.frag.spv create mode 100644 gsk/resources/vulkan/border.vert.glsl create mode 100644 gsk/resources/vulkan/border.vert.spv create mode 100644 gsk/resources/vulkan/rounded-rect.glsl diff --git a/gsk/Makefile.am b/gsk/Makefile.am index e176dd25c6..e74529c806 100644 --- a/gsk/Makefile.am +++ b/gsk/Makefile.am @@ -25,6 +25,7 @@ noinst_LTLIBRARIES = if HAVE_VULKAN gsk_private_vulkan_source_h = \ gskvulkanblendpipelineprivate.h \ + gskvulkanborderpipelineprivate.h \ gskvulkanbufferprivate.h \ gskvulkanclipprivate.h \ gskvulkancolorpipelineprivate.h \ @@ -41,6 +42,7 @@ gsk_private_vulkan_source_h = \ gskvulkanshaderprivate.h gsk_private_vulkan_source_c = \ gskvulkanblendpipeline.c \ + gskvulkanborderpipeline.c \ gskvulkanbuffer.c \ gskvulkanclip.c \ gskvulkancolorpipeline.c \ @@ -55,6 +57,8 @@ gsk_private_vulkan_source_c = \ gskvulkanrenderer.c \ gskvulkanrenderpass.c \ gskvulkanshader.c +gsk_private_vulkan_include_shaders = \ + resources/vulkan/rounded-rect.glsl gsk_private_vulkan_shaders = \ resources/vulkan/blend-clip.frag.glsl \ resources/vulkan/blend-clip-rounded.frag.glsl \ @@ -62,6 +66,12 @@ gsk_private_vulkan_shaders = \ resources/vulkan/blend-clip.vert.glsl \ resources/vulkan/blend.frag.glsl \ resources/vulkan/blend.vert.glsl \ + resources/vulkan/border-clip.frag.glsl \ + resources/vulkan/border-clip.vert.glsl \ + resources/vulkan/border-clip-rounded.frag.glsl \ + resources/vulkan/border-clip-rounded.vert.glsl \ + resources/vulkan/border.frag.glsl \ + resources/vulkan/border.vert.glsl \ resources/vulkan/color-clip.frag.glsl \ resources/vulkan/color-clip-rounded.frag.glsl \ resources/vulkan/color-clip-rounded.vert.glsl \ @@ -199,7 +209,7 @@ gskresources.c: gsk.resources.xml $(resource_files) $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< \ --target=$@ --sourcedir=$(srcdir) --c-name _gsk --generate-source --manual-register -EXTRA_DIST += $(resource_files) +EXTRA_DIST += $(resource_files) $(gsk_private_vulkan_include_shaders) CLEANFILES += gsk.resources.xml DISTCLEANFILES += gskresources.h gskresources.c diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index af356d5798..aaa6a922bd 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -593,22 +593,20 @@ gsk_border_node_peek_outline (GskRenderNode *node) return &self->outline; } -float -gsk_border_node_get_width (GskRenderNode *node, - guint i) +const float * +gsk_border_node_peek_widths (GskRenderNode *node) { GskBorderNode *self = (GskBorderNode *) node; - return self->border_width[i]; + return self->border_width; } const GdkRGBA * -gsk_border_node_peek_color (GskRenderNode *node, - guint i) +gsk_border_node_peek_colors (GskRenderNode *node) { GskBorderNode *self = (GskBorderNode *) node; - return &self->border_color[i]; + return self->border_color; } /** diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index 938c948002..52f7bc8b46 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -59,8 +59,8 @@ const gsize gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node); const GskColorStop * gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node); const GskRoundedRect * gsk_border_node_peek_outline (GskRenderNode *node); -float gsk_border_node_get_width (GskRenderNode *node, guint i); -const GdkRGBA * gsk_border_node_peek_color (GskRenderNode *node, guint i); +const float * gsk_border_node_peek_widths (GskRenderNode *node); +const GdkRGBA * gsk_border_node_peek_colors (GskRenderNode *node); GskRenderNode *gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds, cairo_surface_t *surface); cairo_surface_t *gsk_cairo_node_get_surface (GskRenderNode *node); diff --git a/gsk/gskvulkanborderpipeline.c b/gsk/gskvulkanborderpipeline.c new file mode 100644 index 0000000000..ab6509b785 --- /dev/null +++ b/gsk/gskvulkanborderpipeline.c @@ -0,0 +1,163 @@ +#include "config.h" + +#include "gskvulkanborderpipelineprivate.h" + +#include "gskroundedrectprivate.h" + +struct _GskVulkanBorderPipeline +{ + GObject parent_instance; +}; + +typedef struct _GskVulkanBorderInstance GskVulkanBorderInstance; + +struct _GskVulkanBorderInstance +{ + float rect[12]; + float widths[4]; + float colors[16]; +}; + +G_DEFINE_TYPE (GskVulkanBorderPipeline, gsk_vulkan_border_pipeline, GSK_TYPE_VULKAN_PIPELINE) + +static const VkPipelineVertexInputStateCreateInfo * +gsk_vulkan_border_pipeline_get_input_state_create_info (GskVulkanPipeline *self) +{ + static const VkVertexInputBindingDescription vertexBindingDescriptions[] = { + { + .binding = 0, + .stride = sizeof (GskVulkanBorderInstance), + .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE + } + }; + static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = { + { + .location = 0, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, rect), + }, + { + .location = 1, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, rect) + 4 * sizeof (float), + }, + { + .location = 2, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, rect) + 8 * sizeof (float), + }, + { + .location = 3, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, widths), + }, + { + .location = 4, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors), + }, + { + .location = 5, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors) + 4 * sizeof (float), + }, + { + .location = 6, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors) + 8 * sizeof (float), + }, + { + .location = 7, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBorderInstance, colors) + 12 * sizeof (float), + } + }; + static const VkPipelineVertexInputStateCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions), + .pVertexBindingDescriptions = vertexBindingDescriptions, + .vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription), + .pVertexAttributeDescriptions = vertexInputAttributeDescription + }; + + return &info; +} + +static void +gsk_vulkan_border_pipeline_finalize (GObject *gobject) +{ + //GskVulkanBorderPipeline *self = GSK_VULKAN_BORDER_PIPELINE (gobject); + + G_OBJECT_CLASS (gsk_vulkan_border_pipeline_parent_class)->finalize (gobject); +} + +static void +gsk_vulkan_border_pipeline_class_init (GskVulkanBorderPipelineClass *klass) +{ + GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass); + + G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_border_pipeline_finalize; + + pipeline_class->get_input_state_create_info = gsk_vulkan_border_pipeline_get_input_state_create_info; +} + +static void +gsk_vulkan_border_pipeline_init (GskVulkanBorderPipeline *self) +{ +} + +GskVulkanPipeline * +gsk_vulkan_border_pipeline_new (GskVulkanPipelineLayout *layout, + const char *shader_name, + VkRenderPass render_pass) +{ + return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BORDER_PIPELINE, layout, shader_name, render_pass); +} + +gsize +gsk_vulkan_border_pipeline_count_vertex_data (GskVulkanBorderPipeline *pipeline) +{ + return sizeof (GskVulkanBorderInstance); +} + +void +gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline *pipeline, + guchar *data, + const GskRoundedRect *rect, + const float widths[4], + const GdkRGBA colors[4]) +{ + GskVulkanBorderInstance *instance = (GskVulkanBorderInstance *) data; + guint i; + + gsk_rounded_rect_to_float (rect, instance->rect); + for (i = 0; i < 4; i++) + { + instance->widths[i] = widths[i]; + instance->colors[4 * i + 0] = colors[i].red; + instance->colors[4 * i + 1] = colors[i].green; + instance->colors[4 * i + 2] = colors[i].blue; + instance->colors[4 * i + 3] = colors[i].alpha; + } +} + +gsize +gsk_vulkan_border_pipeline_draw (GskVulkanBorderPipeline *pipeline, + VkCommandBuffer command_buffer, + gsize offset, + gsize n_commands) +{ + vkCmdDraw (command_buffer, + 6 * 8, n_commands, + 0, offset); + + return n_commands; +} diff --git a/gsk/gskvulkanborderpipelineprivate.h b/gsk/gskvulkanborderpipelineprivate.h new file mode 100644 index 0000000000..de6d1768a7 --- /dev/null +++ b/gsk/gskvulkanborderpipelineprivate.h @@ -0,0 +1,34 @@ +#ifndef __GSK_VULKAN_BORDER_PIPELINE_PRIVATE_H__ +#define __GSK_VULKAN_BORDER_PIPELINE_PRIVATE_H__ + +#include + +#include "gskvulkanpipelineprivate.h" +#include "gskroundedrect.h" + +G_BEGIN_DECLS + +typedef struct _GskVulkanBorderPipelineLayout GskVulkanBorderPipelineLayout; + +#define GSK_TYPE_VULKAN_BORDER_PIPELINE (gsk_vulkan_border_pipeline_get_type ()) + +G_DECLARE_FINAL_TYPE (GskVulkanBorderPipeline, gsk_vulkan_border_pipeline, GSK, VULKAN_BORDER_PIPELINE, GskVulkanPipeline) + +GskVulkanPipeline * gsk_vulkan_border_pipeline_new (GskVulkanPipelineLayout * layout, + const char *shader_name, + VkRenderPass render_pass); + +gsize gsk_vulkan_border_pipeline_count_vertex_data (GskVulkanBorderPipeline *pipeline); +void gsk_vulkan_border_pipeline_collect_vertex_data (GskVulkanBorderPipeline *pipeline, + guchar *data, + const GskRoundedRect *rect, + const float widths[4], + const GdkRGBA colors[4]); +gsize gsk_vulkan_border_pipeline_draw (GskVulkanBorderPipeline *pipeline, + VkCommandBuffer command_buffer, + gsize offset, + gsize n_commands); + +G_END_DECLS + +#endif /* __GSK_VULKAN_BORDER_PIPELINE_PRIVATE_H__ */ diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index 6c664ae367..cd362d00b1 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -9,6 +9,7 @@ #include "gskvulkanrenderpassprivate.h" #include "gskvulkanblendpipelineprivate.h" +#include "gskvulkanborderpipelineprivate.h" #include "gskvulkancolorpipelineprivate.h" #include "gskvulkaneffectpipelineprivate.h" #include "gskvulkanlineargradientpipelineprivate.h" @@ -326,7 +327,10 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, { "linear-clip-rounded", gsk_vulkan_linear_gradient_pipeline_new }, { "color-matrix", gsk_vulkan_effect_pipeline_new }, { "color-matrix-clip", gsk_vulkan_effect_pipeline_new }, - { "color-matrix-clip-rounded", gsk_vulkan_effect_pipeline_new } + { "color-matrix-clip-rounded", gsk_vulkan_effect_pipeline_new }, + { "border", gsk_vulkan_border_pipeline_new }, + { "border-clip", gsk_vulkan_border_pipeline_new }, + { "border-clip-rounded", gsk_vulkan_border_pipeline_new } }; g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index c500d908cc..c92375e30b 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -7,6 +7,7 @@ #include "gskrenderer.h" #include "gskroundedrectprivate.h" #include "gskvulkanblendpipelineprivate.h" +#include "gskvulkanborderpipelineprivate.h" #include "gskvulkanclipprivate.h" #include "gskvulkancolorpipelineprivate.h" #include "gskvulkaneffectpipelineprivate.h" @@ -30,6 +31,7 @@ typedef enum { GSK_VULKAN_OP_LINEAR_GRADIENT, GSK_VULKAN_OP_OPACITY, GSK_VULKAN_OP_COLOR_MATRIX, + GSK_VULKAN_OP_BORDER, /* GskVulkanOpPushConstants */ GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS } GskVulkanOpType; @@ -110,9 +112,9 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, case GSK_NOT_A_RENDER_NODE: g_assert_not_reached (); return; - case GSK_BORDER_NODE: case GSK_INSET_SHADOW_NODE: case GSK_OUTSET_SHADOW_NODE: + case GSK_REPEAT_NODE: case GSK_SHADOW_NODE: case GSK_BLEND_NODE: case GSK_CROSS_FADE_NODE: @@ -210,6 +212,20 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, g_array_append_val (self->render_ops, op); return; + case GSK_BORDER_NODE: + if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_BORDER; + else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_BORDER_CLIP; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_BORDER_CLIP_ROUNDED; + else + FALLBACK ("Border nodes can't deal with clip type %u\n", constants->clip.type); + op.type = GSK_VULKAN_OP_BORDER; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); + g_array_append_val (self->render_ops, op); + return; + case GSK_CONTAINER_NODE: { guint i; @@ -499,6 +515,7 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, case GSK_VULKAN_OP_COLOR: case GSK_VULKAN_OP_LINEAR_GRADIENT: case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: + case GSK_VULKAN_OP_BORDER: break; } } @@ -543,6 +560,11 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) n_bytes += op->render.vertex_count; break; + case GSK_VULKAN_OP_BORDER: + op->render.vertex_count = gsk_vulkan_border_pipeline_count_vertex_data (GSK_VULKAN_BORDER_PIPELINE (op->render.pipeline)); + n_bytes += op->render.vertex_count; + break; + default: g_assert_not_reached (); case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: @@ -644,6 +666,18 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, } break; + case GSK_VULKAN_OP_BORDER: + { + op->render.vertex_offset = offset + n_bytes; + gsk_vulkan_border_pipeline_collect_vertex_data (GSK_VULKAN_BORDER_PIPELINE (op->render.pipeline), + data + n_bytes + offset, + gsk_border_node_peek_outline (op->render.node), + gsk_border_node_peek_widths (op->render.node), + gsk_border_node_peek_colors (op->render.node)); + n_bytes += op->render.vertex_count; + } + break; + default: g_assert_not_reached (); case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: @@ -684,6 +718,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, case GSK_VULKAN_OP_COLOR: case GSK_VULKAN_OP_LINEAR_GRADIENT: case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: + case GSK_VULKAN_OP_BORDER: break; } } @@ -829,6 +864,27 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, current_draw_index, 1); break; + case GSK_VULKAN_OP_BORDER: + if (current_pipeline != op->render.pipeline) + { + current_pipeline = op->render.pipeline; + vkCmdBindPipeline (command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + gsk_vulkan_pipeline_get_pipeline (current_pipeline)); + vkCmdBindVertexBuffers (command_buffer, + 0, + 1, + (VkBuffer[1]) { + gsk_vulkan_buffer_get_buffer (vertex_buffer) + }, + (VkDeviceSize[1]) { op->render.vertex_offset }); + current_draw_index = 0; + } + current_draw_index += gsk_vulkan_border_pipeline_draw (GSK_VULKAN_BORDER_PIPELINE (current_pipeline), + command_buffer, + current_draw_index, 1); + break; + case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: gsk_vulkan_push_constants_push_vertex (&op->constants.constants, command_buffer, diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index 6bfb8b0573..ea9c751637 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -22,6 +22,9 @@ typedef enum { GSK_VULKAN_PIPELINE_COLOR_MATRIX, GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP, GSK_VULKAN_PIPELINE_COLOR_MATRIX_CLIP_ROUNDED, + GSK_VULKAN_PIPELINE_BORDER, + GSK_VULKAN_PIPELINE_BORDER_CLIP, + GSK_VULKAN_PIPELINE_BORDER_CLIP_ROUNDED, /* add more */ GSK_VULKAN_N_PIPELINES } GskVulkanPipelineType; diff --git a/gsk/resources/vulkan/border-clip-rounded.frag.glsl b/gsk/resources/vulkan/border-clip-rounded.frag.glsl new file mode 100644 index 0000000000..bf4ad650b1 --- /dev/null +++ b/gsk/resources/vulkan/border-clip-rounded.frag.glsl @@ -0,0 +1,34 @@ +#version 420 core + +#include "rounded-rect.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in vec4 inColor; +layout(location = 2) in vec4 inRect; +layout(location = 3) in vec4 inCornerWidths; +layout(location = 4) in vec4 inCornerHeights; +layout(location = 5) in vec4 inBorderWidths; +layout(location = 6) in flat vec4 inClipBounds; +layout(location = 7) in flat vec4 inClipWidths; +layout(location = 8) in flat vec4 inClipHeights; + +layout(location = 0) out vec4 color; + +vec4 +clip (vec4 color) +{ + RoundedRect r = RoundedRect (vec4(inClipBounds.xy, inClipBounds.xy + inClipBounds.zw), inClipWidths, inClipHeights); + + return color * rounded_rect_coverage (r, inPos); +} + +void main() +{ + RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths, inCornerHeights); + RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths); + + float alpha = clamp (rounded_rect_coverage (routside, inPos) - + rounded_rect_coverage (rinside, inPos), + 0.0, 1.0); + color = clip (inColor); +} diff --git a/gsk/resources/vulkan/border-clip-rounded.frag.spv b/gsk/resources/vulkan/border-clip-rounded.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..401d7ae1c644151f3542873c08f79f737ad2a4ee GIT binary patch literal 9832 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 N<}gMddm`^U`2YL_YXtxR literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/border-clip.frag.glsl b/gsk/resources/vulkan/border-clip.frag.glsl new file mode 100644 index 0000000000..5f9d7090a1 --- /dev/null +++ b/gsk/resources/vulkan/border-clip.frag.glsl @@ -0,0 +1,23 @@ +#version 420 core + +#include "rounded-rect.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in flat vec4 inColor; +layout(location = 2) in flat vec4 inRect; +layout(location = 3) in flat vec4 inCornerWidths; +layout(location = 4) in flat vec4 inCornerHeights; +layout(location = 5) in flat vec4 inBorderWidths; + +layout(location = 0) out vec4 color; + +void main() +{ + RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths, inCornerHeights); + RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths); + + float alpha = clamp (rounded_rect_coverage (routside, inPos) - + rounded_rect_coverage (rinside, inPos), + 0.0, 1.0); + color = inColor * alpha; +} diff --git a/gsk/resources/vulkan/border-clip.frag.spv b/gsk/resources/vulkan/border-clip.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..ab43d3dec875290b475213235d1216dd3ea52201 GIT binary patch literal 9008 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 OfSqHUKF_F{XY{`mRA{&W literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/border-clip.vert.glsl b/gsk/resources/vulkan/border-clip.vert.glsl new file mode 100644 index 0000000000..5de7a12f70 --- /dev/null +++ b/gsk/resources/vulkan/border-clip.vert.glsl @@ -0,0 +1,117 @@ +#version 420 core + +layout(location = 0) in vec4 inRect; +layout(location = 1) in vec4 inCornerWidths; +layout(location = 2) in vec4 inCornerHeights; +layout(location = 3) in vec4 inBorderWidths; +layout(location = 4) in mat4 inBorderColors; + +layout(push_constant) uniform PushConstants { + mat4 mvp; + vec4 clip_bounds; + vec4 clip_widths; + vec4 clip_heights; +} push; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat vec4 outColor; +layout(location = 2) out flat vec4 outRect; +layout(location = 3) out flat vec4 outCornerWidths; +layout(location = 4) out flat vec4 outCornerHeights; +layout(location = 5) out flat vec4 outBorderWidths; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 offsets[6] = { vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(1.0, 1.0), + vec2(0.0, 1.0), + vec2(1.0, 0.0) }; + +#define TOP 0 +#define RIGHT 1 +#define BOTTOM 2 +#define LEFT 3 + +#define TOP_LEFT 0 +#define TOP_RIGHT 1 +#define BOTTOM_RIGHT 2 +#define BOTTOM_LEFT 3 + +#define SLICE_TOP_LEFT 0 +#define SLICE_TOP 1 +#define SLICE_TOP_RIGHT 2 +#define SLICE_RIGHT 3 +#define SLICE_BOTTOM_RIGHT 4 +#define SLICE_BOTTOM 5 +#define SLICE_BOTTOM_LEFT 6 +#define SLICE_LEFT 7 + +vec4 intersect(vec4 a, vec4 b) +{ + a = vec4(a.xy, a.xy + a.zw); + b = vec4(b.xy, b.xy + b.zw); + vec4 result = vec4(max(a.xy, b.xy), min(a.zw, b.zw)); + if (any (greaterThanEqual (result.xy, result.zw))) + return vec4(0.0,0.0,0.0,0.0); + return vec4(result.xy, result.zw - result.xy); +} + +void main() { + int slice_index = gl_VertexIndex / 6; + int vert_index = gl_VertexIndex % 6; + + vec4 corner_widths = max (inCornerWidths, inBorderWidths.wyyw); + vec4 corner_heights = max (inCornerHeights, inBorderWidths.xxzz); + + vec4 rect; + + switch (slice_index) + { + case SLICE_TOP_LEFT: + rect = vec4(inRect.xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]); + vert_index = (vert_index + 3) % 6; + break; + case SLICE_TOP: + rect = vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.z - corner_widths[TOP_LEFT] - corner_widths[TOP_RIGHT], inBorderWidths[TOP]); + outColor = inBorderColors[TOP]; + break; + case SLICE_TOP_RIGHT: + rect = vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT], corner_heights[TOP_RIGHT]); + break; + case SLICE_RIGHT: + rect = vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT], inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]); + outColor = inBorderColors[RIGHT]; + break; + case SLICE_BOTTOM_RIGHT: + rect = vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w - corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]); + break; + case SLICE_BOTTOM: + rect = vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM], inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]); + break; + case SLICE_BOTTOM_LEFT: + rect = vec4(inRect.x, inRect.y + inRect.w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT], corner_heights[BOTTOM_LEFT]); + vert_index = (vert_index + 3) % 6; + break; + case SLICE_LEFT: + rect = vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w - corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]); + break; + } + + rect = intersect (rect, push.clip_bounds); + vec2 pos; + if ((slice_index % 4) != 0 || (vert_index % 3) != 2) + pos = rect.xy + rect.zw * offsets[vert_index]; + else + pos = rect.xy + rect.zw * vec2(1.0 - offsets[vert_index].x, offsets[vert_index].y); + gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); + outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4]; + outPos = pos; + outRect = inRect; + outCornerWidths = inCornerWidths; + outCornerHeights = inCornerHeights; + outBorderWidths = inBorderWidths; +} diff --git a/gsk/resources/vulkan/border-clip.vert.spv b/gsk/resources/vulkan/border-clip.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..5a505d8ebc4bb7d63c66d72da4dad16ab2004b97 GIT binary patch literal 8952 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 literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/border.frag.glsl b/gsk/resources/vulkan/border.frag.glsl new file mode 100644 index 0000000000..5f9d7090a1 --- /dev/null +++ b/gsk/resources/vulkan/border.frag.glsl @@ -0,0 +1,23 @@ +#version 420 core + +#include "rounded-rect.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in flat vec4 inColor; +layout(location = 2) in flat vec4 inRect; +layout(location = 3) in flat vec4 inCornerWidths; +layout(location = 4) in flat vec4 inCornerHeights; +layout(location = 5) in flat vec4 inBorderWidths; + +layout(location = 0) out vec4 color; + +void main() +{ + RoundedRect routside = RoundedRect (vec4(inRect.xy, inRect.xy + inRect.zw), inCornerWidths, inCornerHeights); + RoundedRect rinside = rounded_rect_shrink (routside, inBorderWidths); + + float alpha = clamp (rounded_rect_coverage (routside, inPos) - + rounded_rect_coverage (rinside, inPos), + 0.0, 1.0); + color = inColor * alpha; +} diff --git a/gsk/resources/vulkan/border.frag.spv b/gsk/resources/vulkan/border.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..ab43d3dec875290b475213235d1216dd3ea52201 GIT binary patch literal 9008 zcmai&d7PDH6~|wg89*2n5O6~sTyX(KQN)eKWKc&zaNn-O+zWGcxHI0lgV6?LmSx$d z?F*HamhFp1CS;aomS&diYWu#MOKE+-_r3?8-hX=Ge4gL$cg}O3^PKm&&)k`|(ff_f zvQhjSmko}}n$M(cG(5{DWMi6RchAb6*~5+U?72rDVZcsVTQkm>owLrYol#rcTdnC> zgyT$XId(R7F?Kn21vZhn#Rz_2yXTZr-_THLxUqhqQW~h% zDy4F@Ug>L8*Hw%gm&8?TeFG!qG@yfsw3ZIyJ6WSLFi;&Dt`3uHxG{6x>LZWWvaEv| z#^WEtoI8QB-dnDY49mx7lhe66V6^tx{+GF?7i|+LQGS)@zk|>8fhE(T{7p&;I4U{z`RC zf1_FVq-+oLdMkg)=9RYBKHR8}^fhKBi_coOdT!X9q%XUf1G7iFGq!p(DeF>Ca}W2| ztF3A#O-sWiH_G}-<-nAs8d9JlDe29}KK2SWTh3A3GnD5C%L%sFhwK+eb zz^{bU?^0u+6~8`s{ysM3d{xe`37*GaC$FsDKL5txdHm*_$NXD^=ksraw^nbhe>*&_ zcT0iaQQ%u!^KDUczuOqo`F9og-35LRyj-%n*8F=5{`(62{sMmh&U|*$n*U(I|4@NH z{6Bnb_6R&bmvQnuw#~gf&d4WmaHRRZJF+egc&&0(Db9TdQ3vN*9C)=kxfTaqZ2=l* zu`ygNb33&1d;e5x&5sokW14qSwRUpz6Lenw0aEvV3Vmt*;qh#(G-tKeOlh2VShcoz zuwJgzpP%2Jor9jflk*DvLU`}MP=9Y;m-k?`wtUb=xXvYo_)>wdD)4fFd#Cmd4h;H| z&FB59gFxz?(WA=`zjtZN4OtwB5uG={MY+m&4YypZebf{$ZV(`Hb?4vhNMwHYwi zN;P$JP04llv^R6TW7WdUKMihfedgbl(Ol~0F=jfWG0rn)FGk~y(RU~@&N&FtoFT>t6dE^HL0U*3cHMEpu{ z_?=(E>~Hw1VBbf~_nbw%`9?6~?dhY8)@D!L*JF%hG4;bh_GmXIyO-3$w>v)jlA7z< zm;GEc+qgAi_fKN=X|B1Dk^jxLj?ej`Tnp}5Hzv5}JLR5fx%n>2vHLJy?q`_)nf@xk z{HX1vQ{ExGql%Dr!bd%nDHf_sj;%TU!%2CHd44iWnTNE&+zTut+Fh}b2NG`1VA zrg@(1%_chInoH5lWz1Pvz$u&tgiq&-#C3IQN8a`-8sgb3s%$TJCsMh^TD1ueZEim{5{|Lexj9|CAIyL5l`PZmec^s{nMBB&(D;P z-#_f1_qM;6MKArm%%1JZ80Yj#aM~k(_euGN0>7rfuPg8y3w(2d-H1p={Emb>e`~^>zpcRUD)74#?)-Za?)-ZT{JsLeKjF@QAmPq`u)rTG@P`vV9sEeb z9|J$0^F^FN^Ph_O-j-rqFz2e@%o$W$j;TM% zd0D~e^9(-qvoJN!j5umK8*EK}CybiT0joz%=YpfAH10ffeNof-VCSko%{sB3;}e_& zYrFunM$fJB))Mt!2-a`?7c=@;zxqX(n)QpL{!75co?eQk9`#=aj`~aB*k>vED1d&Q*844UB4$=at}CFMZdq zLf02@*XD7qm&Uyst}oVm4cNKruIHVv=J}h>_*%^Myl*^LQy5=|smJ&K>vK)rXA~B7 zydE6&rtkF)==vh=jd@)0{l5uaU)1|%uyfTnVo(zEgobbTA>%NWLYVrsFccY&Q(JY(-h(-(Vs57@ctv8VTftx2DI zx{*;W_VhlmxzqRZezuRj%{{eYQQJ-6*i(8QKZvd`_VgjJTFm<}IQEpzyBS?y z%)14w7JK{%*j(zd$B%-oQJ;I<%%~Q7{1~{n$B(0_#~wccR?~daJ$@1%d#r-vUi=hT zU+n4Ad0g?c@)>k}v8T_1)nZSd1Di`d_VjtMHR*Ftw=$}^_E^R*V7p`bZqIr6z6kg1 z>f6F758s!-SLVJu80GWH=()QSn~a&ydHT(98>7C+@nvwVy$vi6-&eq%G3VXIC=cIP z!RvG1-Hh^B`)gp=-iA3(zd5!t>Wds-2glm?g5}}+26!{(y!#mC;rk|dL+-nuQ66i5 z3+&qFbDn;4+{36Za(o*cYd;8Xg|gDJKwq< z$u&P)$AEu^*^{MMto`#`kC(s4 zTd?b|#A5y5fz>1C_h8pgWBveFkM;iucAmQ5X<{wM_)haDu(b?g#;0}s8D8weU(nQ} zj=zHaY%Im1*1v((x6scejDN?Rr*0pfVDzyM`u>5b*#~jt{wKKDhbPh0Bjzcv>!*Eq z8m=CFcn0h|b^8!&IYuA;1-2G@V|-f2zv0C`Jd36tbvy^&jHP|}4_rO^;15pcsoRIq za3A}iZxp6xAHhV5y1UpaNKJ3isV;}VGgsIsFapax|F7{y(ntH@c2D^UR zhh5OrqYqQS&QrG!v6f@>VJg^K?2Yl(;ob5mxu=2s+<0c}m$BX>kLNx=2gdD+u67Hz zo%hZja5evK@89)}Q{NNp9Tb0WnhrNsJ^m)L7ufqupTAGY<8K~Q(Yr98y|8)IGL3QX z98YK52eY3u82y`vS{FISCj8(6pObTYYy1qjIeW0EeP1;7;0J(RYZ-qvbZ-a3)wDLa z50Fay`O&(M4?@@z1%>N^TeJ@{O3TJOx)|EgS!%b9N0aD|9G%-;&1vV OfSqHUKF_F{XY{`mRA{&W literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/border.vert.glsl b/gsk/resources/vulkan/border.vert.glsl new file mode 100644 index 0000000000..48efbc7e40 --- /dev/null +++ b/gsk/resources/vulkan/border.vert.glsl @@ -0,0 +1,106 @@ +#version 420 core + +layout(location = 0) in vec4 inRect; +layout(location = 1) in vec4 inCornerWidths; +layout(location = 2) in vec4 inCornerHeights; +layout(location = 3) in vec4 inBorderWidths; +layout(location = 4) in mat4 inBorderColors; + +layout(push_constant) uniform PushConstants { + mat4 mvp; + vec4 clip_bounds; + vec4 clip_widths; + vec4 clip_heights; +} push; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat vec4 outColor; +layout(location = 2) out flat vec4 outRect; +layout(location = 3) out flat vec4 outCornerWidths; +layout(location = 4) out flat vec4 outCornerHeights; +layout(location = 5) out flat vec4 outBorderWidths; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 offsets[6] = { vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(1.0, 1.0), + vec2(0.0, 1.0), + vec2(1.0, 0.0) }; + +#define TOP 0 +#define RIGHT 1 +#define BOTTOM 2 +#define LEFT 3 + +#define TOP_LEFT 0 +#define TOP_RIGHT 1 +#define BOTTOM_RIGHT 2 +#define BOTTOM_LEFT 3 + +#define SLICE_TOP_LEFT 0 +#define SLICE_TOP 1 +#define SLICE_TOP_RIGHT 2 +#define SLICE_RIGHT 3 +#define SLICE_BOTTOM_RIGHT 4 +#define SLICE_BOTTOM 5 +#define SLICE_BOTTOM_LEFT 6 +#define SLICE_LEFT 7 + +void main() { + int slice_index = gl_VertexIndex / 6; + int vert_index = gl_VertexIndex % 6; + + vec4 corner_widths = max (inCornerWidths, inBorderWidths.wyyw); + vec4 corner_heights = max (inCornerHeights, inBorderWidths.xxzz); + + vec4 rect; + + switch (slice_index) + { + case SLICE_TOP_LEFT: + rect = vec4(inRect.xy, corner_widths[TOP_LEFT], corner_heights[TOP_LEFT]); + vert_index = (vert_index + 3) % 6; + break; + case SLICE_TOP: + rect = vec4(inRect.x + corner_widths[TOP_LEFT], inRect.y, inRect.z - corner_widths[TOP_LEFT] - corner_widths[TOP_RIGHT], inBorderWidths[TOP]); + outColor = inBorderColors[TOP]; + break; + case SLICE_TOP_RIGHT: + rect = vec4(inRect.x + inRect.z - corner_widths[TOP_RIGHT], inRect.y, corner_widths[TOP_RIGHT], corner_heights[TOP_RIGHT]); + break; + case SLICE_RIGHT: + rect = vec4(inRect.x + inRect.z - inBorderWidths[RIGHT], inRect.y + corner_heights[TOP_RIGHT], inBorderWidths[RIGHT], inRect.w - corner_heights[TOP_RIGHT] - corner_heights[BOTTOM_RIGHT]); + outColor = inBorderColors[RIGHT]; + break; + case SLICE_BOTTOM_RIGHT: + rect = vec4(inRect.x + inRect.z - corner_widths[BOTTOM_RIGHT], inRect.y + inRect.w - corner_heights[BOTTOM_RIGHT], corner_widths[BOTTOM_RIGHT], corner_heights[BOTTOM_RIGHT]); + break; + case SLICE_BOTTOM: + rect = vec4(inRect.x + corner_widths[BOTTOM_LEFT], inRect.y + inRect.w - inBorderWidths[BOTTOM], inRect.z - corner_widths[BOTTOM_LEFT] - corner_widths[BOTTOM_RIGHT], inBorderWidths[BOTTOM]); + break; + case SLICE_BOTTOM_LEFT: + rect = vec4(inRect.x, inRect.y + inRect.w - corner_heights[BOTTOM_LEFT], corner_widths[BOTTOM_LEFT], corner_heights[BOTTOM_LEFT]); + vert_index = (vert_index + 3) % 6; + break; + case SLICE_LEFT: + rect = vec4(inRect.x, inRect.y + corner_heights[TOP_LEFT], inBorderWidths[LEFT], inRect.w - corner_heights[TOP_LEFT] - corner_heights[BOTTOM_LEFT]); + break; + } + + vec2 pos; + if ((slice_index % 4) != 0 || (vert_index % 3) != 2) + pos = rect.xy + rect.zw * offsets[vert_index]; + else + pos = rect.xy + rect.zw * vec2(1.0 - offsets[vert_index].x, offsets[vert_index].y); + gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); + outColor = inBorderColors[((gl_VertexIndex / 3 + 15) / 4) % 4]; + outPos = pos; + outRect = inRect; + outCornerWidths = inCornerWidths; + outCornerHeights = inCornerHeights; + outBorderWidths = inBorderWidths; +} diff --git a/gsk/resources/vulkan/border.vert.spv b/gsk/resources/vulkan/border.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..384eebeae85d3da07f94bec695a59534439e6b11 GIT binary patch literal 7216 zcmZ9Q2b5h^6^8GWOnO2{2qA=Ik`N$;5J(pTfrt|p(Tt#ApG;<6lBbjR#(9$f){Kat z*g%)Pi;BJXhPv#%F1y%uEyPL(_51ESI~?zw?3{o9d+&43-us;UW?on4^2tTf!OxUp zYe!K&bBa#%qL^Ovlw;qnOLnbojSsKguyLIZvx=_LPoLSvu_f;2|AT||hROnDIkEy- zg**ruM23+Q2s#5f6IqXJL^dN`{B&Z!5!_u&EBbZ~^zGi=x9fs|q0!NS*7%hpwSkd( zqc$*HAFB;Zm?tlNtz@@dZ@!Ay^mUQX62;aky$+h%d3OCdoYt+UDF0T)dA84UFhxykVJ4(xC z$slh{>W%Z8W5czvoL~9CJO^s^{Rh}yIgj;=d3Gj)d2EHZ5DfTrmo=_8E-o4K8ia2i z8sE_zX^yphddm98+NGgfqpP?Nhta0>=qZk;{^Z_Y8*8U;Y)|6F+M2EUc)i)czpL!0 zys-<3?LX8yu%p>%jSn_V0k*s3^*MNWw46&n{uM(b_0fU7%|ngh)=}OwQ1YpoJ;mfQ z-V;~yN2}A$dl3_jvLF4%15EgIeW_U ziS7TI*2h|&^XZ5^Qn%-e5vD42d#&!?wd<#Dj_TeEb)P=G1{r6SxVyypT;3gZ&+|?) zwNE~-?_<22bMM5<8v9H_^bg%V`s5rhfZ~{pGgQCr8Rxum{TXLoa(fWhca6x+JD%re zA0jugwzh9q*^{u@A8pR_vQ5Cw(edpGD}?7>$wZMYrzST9aNz^ORR##%Qd%^Qn7Yw~lB+Am@>HhN-@ACb72?~&-90sZ$d8XNmnA57c=?0b_f@*P5VetGjz_nykderjN! zSnpb}YlQsSMd#jP2C8`yQi?+$S6^IoudEAG3K3CuC{nMs#h%xbF>lA5Kcx*x2)FaGp>1xEAah?$LO4-w|@^dl-E$ zE$K=A_y~^otKTbxLXZk5% z@6m3$q5V`uPO%o0sTA=HcCF88iF0&5W89l{kc+iegT0fXuL0+4osKT2#A7d%SZgiV zJvguP8RJ^kSXpL?mSeCX@I&UGf@8fPKqwH~qm8xZ@x5%K(QLhRFK z#4}-h&T@o&fgT=QVjEx_tC( zpu|OCKF*;%dZx{}mND)_hLIX#eoGklBl7wWCOz+u=REdO2V0+fFHb_351%I|pS*@6 zaPkwWJ_o_Z$s6Z6Zy?qBG!q~78AUf%KGu5**gfTS9YdFoxm)1s+~aWa;d2PQ63OQ| zj4mH_z8vfxoZoouQD<#=-PWVW9-JPQ`S5vK^2zJ=bU68mRJUhCIr{8)U6!hm#MVo50n%-vK8deSIg`oL$3s?a^0ld7n0-JNHG5??%iw z@6&q{AM3vt-96?tc^|s`MC#M~!N$qQ+#di}>-|AE`SAHr^2z7^Fr0kM{SmNn@)7q@ z@Cqb910O?|k9vO`Y^;35eFE&B^0-f;%j@I$`V>;l_tS}wxj%z$oP5N67F_M+=iuZc z?q;yD^0BASgR8lG0Zu;p`$e!dHm92r?a^Otd4D&d$J}26n{VFVFQdzc&sUO9elNZX zCm%jvOFns@z78ipkptVHs-ZzVoz@@;fuU`|2Fy;qt89qNIkgXKIgvDTen`8yEz9P>Ed&fg-geHY@|=Apl9xQ}}necXpWcO#QK+WQd4XY&2v ztw{Wx^&haD;zP($-~WPhUyX7~C(?yPejV7%&t7(dyO0^^^7>2$cPIX8eAFkQJE#0a z;(EaDNt->q4=iUr%+b1sfaRNYqmO&p1GfU~cV6zry{qdNwL1m809$;2b1J%=_a@%GE79fsjw}3Df#to+ zapzW}%ged`GR8IN!;IQo(|w)}mUlmcNsqd$gSRf){LV~0;?4s5Zq(-YXX;_w0A8MK iewU^mwoTww$>#TJ>S5agUXg5m$EJRN(ZT)iDE= r.bounds.z || p.y >= r.bounds.w) + return 0.0; + + vec2 rad_tl = vec2(r.corner_widths.x, r.corner_heights.x); + vec2 rad_tr = vec2(r.corner_widths.y, r.corner_heights.y); + vec2 rad_br = vec2(r.corner_widths.z, r.corner_heights.z); + vec2 rad_bl = vec2(r.corner_widths.w, r.corner_heights.w); + + vec2 ref_tl = r.bounds.xy + vec2( r.corner_widths.x, r.corner_heights.x); + vec2 ref_tr = r.bounds.zy + vec2(-r.corner_widths.y, r.corner_heights.y); + vec2 ref_br = r.bounds.zw + vec2(-r.corner_widths.z, -r.corner_heights.z); + vec2 ref_bl = r.bounds.xw + vec2( r.corner_widths.w, -r.corner_heights.w); + + float d_tl = ellipsis_coverage(p, ref_tl, rad_tl); + float d_tr = ellipsis_coverage(p, ref_tr, rad_tr); + float d_br = ellipsis_coverage(p, ref_br, rad_br); + float d_bl = ellipsis_coverage(p, ref_bl, rad_bl); + + vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl); + + bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y, + p.x > ref_tr.x && p.y < ref_tr.y, + p.x > ref_br.x && p.y > ref_br.y, + p.x < ref_bl.x && p.y > ref_bl.y); + + return 1.0 - dot(vec4(is_out), corner_coverages); +} + +RoundedRect +rounded_rect_shrink (RoundedRect r, vec4 amount) +{ + vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz; + vec4 new_widths = max (r.corner_widths - amount.wyyw, 0.0); + vec4 new_heights = max (r.corner_heights - amount.xxzz, 0.0); + + return RoundedRect (new_bounds, new_widths, new_heights); +} + +#endif -- 2.30.2